from __future__ import annotations

from dataclasses import dataclass
from importlib.resources import files
import json
from typing import Any, Dict, Optional


@dataclass
class Material:
    name: str
    density: float  # kN/m3 或等效
    strength: float  # 代表强度（如抗拉强度 kN/m2 或 MPa）
    extra: Dict[str, Any]


class DataProvider:
    """从数据资源目录加载标准参数与材料库。"""

    def __init__(self) -> None:
        self._cache: Dict[str, Any] = {}

    def _load_json(self, filename: str) -> Any:
        key = f"json:{filename}"
        if key in self._cache:
            return self._cache[key]
        try:
            data_bytes = files("gssgca.data_resources").joinpath(filename).read_bytes()
            data = json.loads(data_bytes.decode("utf-8"))
            self._cache[key] = data
            return data
        except Exception:
            # 最小可用兜底
            if filename == "materials.json":
                data = {
                    "steel_Q235": {"density": 78.5, "strength": 235.0, "unit": "kN/m3, MPa"},
                    "wire_rope_1770": {"density": 78.5, "strength": 1770.0, "unit": "kN/m3, MPa"},
                }
            elif filename == "rope_catalog.json":
                data = {
                    "wire_ropes": [
                        {"diameter_mm": 26, "breaking_kN": 410, "unit_weight_N_per_m": 26.0 * 0.0036},
                        {"diameter_mm": 28, "breaking_kN": 470, "unit_weight_N_per_m": 28.0 * 0.0036},
                        {"diameter_mm": 32, "breaking_kN": 600, "unit_weight_N_per_m": 32.0 * 0.0036},
                    ]
                }
            elif filename == "standards.json":
                data = {
                    "partial_factors": {"permanent": 1.2, "variable": 1.4},
                    "combination_factors": {"leading": 1.0, " accompanying": 0.7},
                }
            else:
                data = {}
            self._cache[key] = data
            return data

    def get_material(self, key: str) -> Optional[Material]:
        db = self._load_json("materials.json")
        m = db.get(key)
        if not m:
            return None
        return Material(name=key, density=float(m.get("density", 0.0)), strength=float(m.get("strength", 0.0)), extra=m)

    def rope_catalog(self) -> Dict[str, Any]:
        return self._load_json("rope_catalog.json")

    def standard_values(self) -> Dict[str, Any]:
        return self._load_json("standards.json")

    def conductor_catalog(self) -> Dict[str, Any]:
        return self._load_json("conductor_catalog.json")

    def fittings_catalog(self) -> Dict[str, Any]:
        return self._load_json("fittings_catalog.json")

    def tower_steel_catalog(self) -> Dict[str, Any]:
        return self._load_json("tower_steel_catalog.json")

    def winch_catalog(self) -> Dict[str, Any]:
        return self._load_json("winch_catalog.json")

    def block_catalog(self) -> Dict[str, Any]:
        return self._load_json("block_catalog.json")


provider = DataProvider()


